State base State transition

상태 디자인 패턴은 “상태가 동작을 제어하고, 상태는 바뀔 수 있다”는 아이디어를 구현한다.
(패턴은 상태 변경 주체가 누구인지는 규정하지 않음)

- 동작을 가지는 실제 클래스로 상태를 정의, 동작들은 상태가 이전될 때 클래스의 변화에 따라 변경됨
- 상태와 상태 전이를 단순히 enum 타입처럼 식별자의 나열로 정의한다.
  실제 상태 변화는 상태 머신(state machine)이라는 특별한 컴포넌트를 두어 수행한다.
상태 기반 상태 전이
class LightSwitch{
State* state;
public:
LightSwitch(){
state=new OffState();
}
void set_state(State* state){
this->state=state;
}
};
struct State{
virtual void on(LightSwitch* ls){
cout<<"Light is already on\n";
}
virtual void off(LightSwitch* ls){
cout<<"Light is already off\n";
}
};
위에서 상태를 클래스로 정의하였다.
상태 클래스 자체의 상태를 전이 시키는 것은 상식적인 개념과 거리가 있으며,
위의 State::on/off 동작은 이미 해당 상태에 있다고 가정하고 있기 때문에 문제가 될 수 있다.
struct OnState: State{
OnState(){ cout<<"Light turned on\n"; }
void off(LightSwitch* ls) override;
};
struct OffState: State{
OffState(){ cout<<"Light truend off\n"; }
void on(LightSwitch* ls) override;
};
void OnState::off(LightSwitch* ls){
cout<<"Switch light off...\n";
ls->set_state(new OffState());
delete this;
}
void OffState::on(LightSwitch* ls){
cout<<"Swtich light on...\n";
ls->set_state(new OnState());
delete this;
}
delete this; 구문은 해당 객체가 이미 생성이 완료되었다는 위험한 가정을 하고 있기 때문에,
매우 위험하다.
//
class LightSwitch{
// ...
void on(){ state->on(this); }
void off(){ state->off(this); }
};
//
LightSwitch ls;
ls.on(); // Swtich light on...\n
ls.off(); // Switch light off...\n